The secret to SciChart’s speed is a bespoke, immediate-mode raster drawing engine. This means that all drawing in SciChart is done ‘immediately’ to the screen, and is cleared and redrawn each time the chart is updated. It is a stark contrast to WPF’s Vector-based retained graphics, which offer high-quality and ease of programming, but at the expense of performance.
Now in SciChart you can take advantage of our immediate-mode drawing API, to create custom RenderableSeries, custom Point-Markers, Draw on top of the chart, or even create your own immediate-mode drawing applications.
The IRenderContext2D Interface
All the drawing to the bitmap layer is achieved with the IRenderContext2D interface. All drawing is done to the RenderSurface, using either a software bitmap rasterizer, or DirectX depending on your RenderSurface.
Using this interface, you can:
- DrawLine - lines of variable stroke width
- DrawQuad - draw a rectangle
- DrawEllipse - draw an ellipse shape
- CreateBrush - Create a brush for fills
- CreatePen - Create a Pen for drawing lines
- CreateSprite - Create a Sprite for drawing repeated small bitmaps
- FillPolygon - Fill an area with a brush
- FillRectangle - Fill a rectangle area
- FillEllipse - Fill an ellipse shape
- DrawText - Draw some text to the render surface
Believe it or not, you can achieve a lot with just those!
LineDrawingContext, PathDrawingContext
With v3.2 or later you can also get a PathDrawingContext, for drawing arbitrary polylines and polygons. These are more efficient APIs for batching up shapes and part of the reason why SciChart v3.2 has a performance boost over previous versions. We recommend using the BeginLine / BeginPolygon methods to draw lines/shapes over DrawLines() FillPolygon() methods above.
| LineDrawingContext, PathDrawingContext |
Copy Code |
|---|---|
/// <summary> /// Begins a Polyline segment, returning the <see cref="IPathDrawingContext"/>. This is the fastest way to draw lines and simply a proxy to <see cref="DrawLines"/> method. /// </summary> /// <param name="pen">The pen for the line segment</param> /// <param name="startX">The start X coordinate (pixel coord)</param> /// <param name="startY">The start Y coordinate (pixel coord)</param> /// <returns>The <see cref="IPathDrawingContext"/> to continue the line</returns> IPathDrawingContext BeginLine(IPen2D pen, double startX, double startY); /// <summary> /// Begins a filled Polygon segment, returning the <see cref="IPathDrawingContext"/>. /// This is the fastest way to draw polygon and simply a proxy to <see cref="FillArea"/> /// method. /// </summary> /// <param name="brush">The brush for the polygon fill</param> /// <param name="startX">The start X coordinate (pixel coord)</param> /// <param name="startY">The start Y coordinate (pixel coord)</param> /// <returns>The <see cref="IPathDrawingContext"/> to continue the polygon</returns> IPathDrawingContext BeginPolygon(IBrush2D brush, double startX, double startY); /// <summary> /// Returns an <see cref="IPathDrawingContext"/> to draw a polyline, or /// collection of PointMarkers /// </summary> /// <example> /// <code> /// var lineContext = renderContext.BeginLine(pen, 0, 0); /// lineContext.LineTo(1, 2); /// lineContext.LineTo(3, 4); /// lineContext.Dispose(); /// </code> /// </example> public interface IPathDrawingContext : IDisposable { /// <summary> /// Starts the context at the specified X,Y coordinate with a specified Pen /// </summary> /// <param name="color">The pen or brush for the drawing operation</param> /// <param name="x">The x-coordinate in pixels</param> /// <param name="y">The y-coordinate in pixels</param> /// <returns>The <see cref="IPathDrawingContext"/> instance, to allow /// fluent API</returns> IPathDrawingContext Begin(IPathColor color, double x, double y); /// <summary> /// Moves the Context to the specified X,Y coordinate. /// </summary> /// <param name="x">The x-coordinate in pixels</param> /// <param name="y">The y-coordinate in pixels</param> /// <returns>The <see cref="IPathDrawingContext"/> instance, to allow /// fluent API</returns> IPathDrawingContext MoveTo(double x, double y); /// <summary> /// Ends the segment, flushing to render target /// </summary> void End(); } | |
Using RenderContext.BeginLines / LineDrawingContext
To use the Path/Line Drawing Context to draw fast PolyLines, use the following code:
| Using RenderContext.BeginLines / LineDrawingContext |
Copy Code |
|---|---|
bool antiAlias = true; float strokeThickness = 1.0f; // Assuming you have a RenderContext instance using (var pen = renderContext.CreatePen(Colors.Red, antiAlias, strokeThickness)) { double x0, y0; double x1, y1; double x2, y2; // Use the line context to draw a Polyline. using (var lineContext = renderContext.BeginLine(pen, x0, y0)) { lineContext.MoveTo(x1, y1); lineContext.MoveTo(x2, y2); } } | |
Parameter Validation & Safety Considerations
The Immediate Mode RenderContext API is a low-level, performance-oriented drawing API. It does not guarantee comprehensive defensive validation of input parameters.
When using this API, it is strongly recommended that you validate all inputs before calling drawing methods. This includes (but is not limited to):
- Ensuring
Pen,Brush, and other drawing resources are notnull - Verifying that point collections are not
nullor empty - Checking array bounds and index ranges
- Validating coordinate values (e.g., avoiding
NaNorInfinity)
Failure to validate inputs may result in runtime exceptions, undefined rendering behavior, or degraded performance.
As a general rule, all parameter validation and consistency checks should be performed by the calling code before invoking RenderContext methods.